﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Lilium.ComponentModel;
using System.Diagnostics;

namespace Lilium.UI.Forms
{
	public sealed class ComboBoxExtension : BasicExtension<ComboBox>
	{
		#region public bool EnableAutocomplete

		private bool m_EnableAutocomplete;

		public bool EnableAutocomplete
		{
			[DebuggerNonUserCodeAttribute]
			get
			{
				return m_EnableAutocomplete;
			}
			[DebuggerNonUserCodeAttribute]
			set
			{
				if (EnableAutocomplete != value)
				{
					m_EnableAutocomplete = value;
					if (!value)
					{
						PreviouslyTypedTextLength = 0;
					}
				}
			}
		}

		#endregion

		protected override void OnAttach()
		{
			Owner.TextChanged += Owner_TextChanged;
		}

		protected override void OnDetach()
		{
			Owner.TextChanged -= Owner_TextChanged;
		}

		private void HandleAutocomplete()
		{
			if (string.IsNullOrEmpty(Owner.Text)
				|| Owner.Items == null
				|| Owner.Items.Count == 0)
			{
				PreviouslyTypedTextLength = 0;
				return;
			}

			var cursorPosition = 
				Owner.SelectionStart < Owner.Text.Length 
				? Owner.SelectionStart 
				: Owner.Text.Length;
			
			var typedText = Owner.Text.Substring(0, cursorPosition);

			if (!string.IsNullOrEmpty(typedText) && (typedText.Length > PreviouslyTypedTextLength) )
			{
				var matchingEntry = Owner.Items
					.Cast<object>()
					.Select(item => new { Item = item, Text = Owner.GetItemText(item) })
					.FirstOrDefault(entry => entry.Text.StartsWith(typedText, StringComparison.CurrentCultureIgnoreCase));

				if (matchingEntry != null)
				{
					Owner.SelectedItem = matchingEntry.Item;
					Owner.Select(cursorPosition, matchingEntry.Text.Length - cursorPosition);
				}
			}

			PreviouslyTypedTextLength = typedText.Length;
		}

		#region Event Handlers

		private void Owner_TextChanged(object sender, EventArgs e)
		{
			if (EnableAutocomplete)
				HandleAutocomplete();
		}

		#endregion

		#region private int PreviouslyTypedTextLength

		private int m_PreviouslyTypedTextLength;

		private int PreviouslyTypedTextLength
		{
			[DebuggerNonUserCodeAttribute]
			get
			{
				return m_PreviouslyTypedTextLength;
			}
			[DebuggerNonUserCodeAttribute]
			set
			{
				m_PreviouslyTypedTextLength = value;
			}
		}

		#endregion
	}
}
